----------------------------------------
--      雪月 常用函数库 by 雪月灬雪歌
----------------------------------------
--to int   '123.01'//1>>0 -- | 位或效率更高
--to float '123.01'+0

---@alias bool boolean

local table_remove = table.remove
local table_concat = table.concat
local ipairs = ipairs
local type = type
local assert = assert
local cj = require 'jass.common'

local floor,ceil = math.floor, math.ceil
base = {

    ---转化为整数id
    ---@param s string
    iid = function( s )
        assert(type(s)=='string','base.iid 传入了一个错误的参数类型')
        local id = 0
        for i=1 , s:len() do
            id = id * 256 + s:byte(i)
        end
        return id
    end,

    B2I = function (b)
        if b then
            return 1
        end
        return 0
    end,
    I2B = function (i)
        if i==0 then
            return false
        end
        return true
    end,
    ---将函数返回值保存为table
    ---例如 table = Params2Table( str:match( "(%d-),(%d)" ) ) 多个返回值存为表
    Params2Table = function ( ... )
        return {...}
    end,

    ---@type fun( int low, int high )
    ---@return int
    randomInt = cj.GetRandomInt,

    -- 高效数据类型转换
    S2I = function (s)
        return s // 1 | 0
    end,
    S2R = function (s)
        return s + 0
    end,

    I2S = function (i)
        return i .. ''
    end,
    I2R = function (i)
        return i + 0
    end,

    R2S = function (r)
        return r .. ''
    end,
    R2I = function (r)
        if r > 0 then
            return floor(r)
        end
        return ceil(r)
    end,
    print = orig_print,
}
orig_print = nil
local toint = base.R2I
---转化为字符串id
base.sid = function ( s )
    s = toint(s)
    local result = {}
    local i = 0
    local x=1
    while x ~= 0 do
        x =  s % 256 --余数
        s = ( s - x ) / 256 --下一个除数
        i = i + 1
        result [ i ] = (x..''):char()
    end
    result [ i ] = nil --去掉末尾0
    return table_concat(result):reverse()
end



---@param s string 完整文本
---@param p string 寻找的字符串
---@param a integer 开始位置
function string.xfind(s,p,a)
    local l = p:len()
    if not a then a = 1 end
    for i=a,s:len() do
        if s:sub(i,i+l-1)==p then
            return i , i+l-1
        end
    end
    return nil,nil
end

math.pow = function(x, y)
    local res = 1
    for i=1 , y do
        res = res * x
    end
    return res
end

function string.calc_width(str, fontSize_UTF8, fontSize_ASCII)
    assert(type(str) == 'string', 'string.calc_width #1 err type')
    fontSize_UTF8 = fontSize_UTF8 or 2
    fontSize_ASCII = fontSize_ASCII or 1

    local lenInByte = str:len()
    local width = 0

    local i = 1
    while i <= lenInByte do
        local curByte = str:byte(i)
        local byteCount = 1

        if curByte > 0 and curByte <= 127 then
            byteCount = 1
        elseif curByte >= 192 and curByte < 223 then
            byteCount = 2
        elseif curByte >= 224 and curByte < 239 then
            byteCount = 3
        elseif curByte >= 240 and curByte <= 247 then
            byteCount = 4
        end

        --local char = string.sub(str, i, i+byteCount-1)
        i = i + byteCount -- 1

        if byteCount == 1 then
            width = width + fontSize_ASCII
        else
            width = width + fontSize_UTF8
            --width = width - fontSize_ASCII*(byteCount-1)
            --print(char)   --中文
        end

        --i = i + 1
    end

    return width // 1 | 0
end

function string.sub_utf8(str, pos_start, pos_end)
    assert(type(str) == 'string', 'string.sub_utf8 #1 err type')

    local lenInByte = str:len()
    local ret = ""

    if not pos_start then
        return ""
    end

    if pos_end then
        if pos_end > lenInByte then
            pos_end = lenInByte
        end
    else
        pos_end = lenInByte
    end

    if pos_end == 0 then
        return ""
    elseif pos_end > 0 then

    else
        pos_end = lenInByte + pos_end + 1
    end

    if pos_start == 0 then
        return ""
    elseif pos_start < 0 then
        pos_start = lenInByte + pos_start + 1
    end

    local i = pos_end - pos_start + 1
    local cur = 1
    local curPos = 0
    while i > 0 and cur <= lenInByte do
        local curByte = str:byte(cur)
        local byteCount = 1
        if not curByte  then
           break
        end

        if curByte > 0 and curByte <= 127 then
            byteCount = 1
        elseif curByte >= 192 and curByte < 223 then
            byteCount = 2
        elseif curByte >= 224 and curByte < 239 then
            byteCount = 3
        elseif curByte >= 240 and curByte <= 247 then
            byteCount = 4
        end

        local char = str:sub( cur, cur+byteCount-1)

        curPos = curPos + 1

        if ( curPos >= pos_start ) then
            i = i - 1
            ret = ret .. char
        end

        cur = cur + byteCount

    end

    return ret
end

local mt_xTable = {
    type = 'xTable',

    insert = function (self, ...)
        local idx = (self[0] or 0)
        for _, v in ipairs({...}) do

            idx = idx + 1
            self[ idx ] = v

        end
        self[0] = idx
        return idx
    end,

    remove = function (self, index)
        if not self[0] or self[0] < 1 then
            return
        end
        self[0] = (self[0] or 0) - 1
        table_remove(self, index)
    end,

    del = function (self)

        local mt = getmetatable(self)
        mt.__mode = 'kv'
        self:reset()

    end,

    reset = function (self, clean)

        if not clean then
            self[1] = nil
            self[2] = nil
        else

            for i = 1, self[0] do

                self[ i ] = nil

            end

        end

        self[0] = 0
    end,

    len = function (self)
        return self[0]
    end,

    ipairs = function (self)
        return ipairs(self)
    end,



}
---返回一个xTable
---自带元方法 insert/remove/del 用法与 table.inset相同，可连续插入
---使用该方法插入可使用 tb[0] 快速查看数组长度
---@param tb? table  自带元方法 insert/remove/del 用法与 table.inset相同，可连续插入
---@return table
function table.new( tb )
    if not tb then
        tb = {
            [0] = 0,
        }
    else
        local i = 0
        for _,_ in ipairs(tb) do
            i = i +1
        end
        tb[0] = i
    end

    return setmetatable( tb,
    {
        __index = mt_xTable
    }
    )
end


local real_require = require
require = function ( lua_path )
    assert( type(lua_path) == "string" , 'require 参数类型错误！ '..type(lua_path)..':'.. lua_path )
    return real_require(lua_path)
end
include = require
